package com.storage.service.impl;

import com.storage.vo.FileStorageIdentity;
import com.storage.service.StorageService;
import com.storage.utill.DateUtil;
import com.storage.utill.FileUtil;
import com.storage.utill.IDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.Files;

@Service
@Slf4j
public class DiskStorageServiceImpl implements StorageService {
    @Value("${storage.disk.defaultPath}")
    private String diskDefaultPath;
    @Override
    public FileStorageIdentity saveFile(byte[] fileBytes, String middleDir) {
        String fileRealPath = applyAddress(middleDir);
        boolean b = FileUtil.saveFile(fileRealPath, fileBytes);
        FileStorageIdentity fileStorageIdentity = new FileStorageIdentity();
        if (b) {
            fileStorageIdentity.setFileSize(fileBytes.length);
            fileStorageIdentity.setAddress(fileRealPath.substring(diskDefaultPath.length()));
            return fileStorageIdentity;
        } else {
            throw new RuntimeException("disk fileStore fail");
        }
    }

    @Override
    public FileStorageIdentity saveFile(InputStream fileInputStream, String middleDir) {
        String fileRealPath = applyAddress(middleDir);
        File file = new File(fileRealPath);
        File parentDir = file.getParentFile();
        if (!parentDir.exists()) {
            if (!parentDir.mkdirs()) {
                throw new RuntimeException("创建目录失败: " + parentDir.getAbsolutePath());
            }
        }

        long totalBytes = 0;
        try (BufferedInputStream bis = new BufferedInputStream(fileInputStream);
             BufferedOutputStream bos = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) {

            byte[] buffer = new byte[8192];
            int len;
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
                totalBytes += len;
            }
            bos.flush();
        } catch (IOException e) {
            throw new RuntimeException("文件写入失败", e);
        }
        FileStorageIdentity identity = new FileStorageIdentity();
        identity.setFileSize(totalBytes);
        identity.setAddress(fileRealPath.substring(diskDefaultPath.length()));
        return identity;
    }

    @Override
    public InputStream getFileStream(String fileAddress) {
        String filePath = diskDefaultPath + fileAddress;
        try {
            return Files.newInputStream(new File(filePath).toPath()); // 调用方记得 close
        } catch (IOException e) {
            throw new RuntimeException("Failed to get file stream", e);
        }
    }

    @Override
    public String applyAddress(String middleDir) {
        String fileStorageId = IDUtil.getUuid();
        String currentDateDir = DateUtil.getCurrentDateDir();
        String relativeAddress = "/" + (middleDir != null ? middleDir + "/" + currentDateDir + "/" + fileStorageId : currentDateDir + "/" + fileStorageId);
        File file = new File(relativeAddress).getParentFile();
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
            if (!mkdirs) {
                throw new RuntimeException("创建目录失败: " + file.getAbsolutePath());
            }
            log.debug("创建目录成功: {}", file.getAbsolutePath());
        }
        return diskDefaultPath + relativeAddress;
    }

    @Override
    public byte[] getFileBytes(String fileAddress) {
        String filePath = diskDefaultPath + fileAddress;
        File file = new File(filePath);
        if (!file.exists()) {
            throw new RuntimeException("File not found: " + filePath);
        }
        try {
            return Files.readAllBytes(file.toPath());
        } catch (IOException e) {
            throw new RuntimeException("Read file failed", e);
        }
    }
}
